#!/usr/bin/env python
# -*- coding: utf-8 -*-

import sys
import os
import json
import urllib.request
import urllib.error
import threading
from datetime import datetime
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, 
                            QHBoxLayout, QPushButton, QLabel, QLineEdit, 
                            QTabWidget, QGroupBox, QFormLayout, QSpinBox, 
                            QComboBox, QTextEdit, QMessageBox, QFileDialog,
                            QCheckBox, QRadioButton, QSlider, QProgressBar,
                            QDialog, QDesktopWidget, QProgressDialog)
from PyQt5.QtCore import Qt, QTimer, pyqtSignal, QObject, QThread
from PyQt5.QtGui import QFont, QIcon, QPixmap

# 导入统一版本信息
from version import APP_NAME, APP_VERSION, UPDATE_URL, DOWNLOAD_BASE_URL

class VersionChecker(QObject):
    """版本检查类，用于检测应用是否有新版本"""
    update_available = pyqtSignal(str, str)  # 信号：新版本号, 下载链接
    check_finished = pyqtSignal(bool)  # 信号：是否检查完成
    
    def __init__(self, current_version, check_url):
        super().__init__()
        self.current_version = current_version
        self.check_url = check_url
        self.latest_version = None
        self.download_url = None
        
    def check_for_updates(self):
        """在后台线程中检查更新"""
        thread = threading.Thread(target=self._perform_check)
        thread.daemon = True
        thread.start()
        
    def _perform_check(self):
        """执行实际的版本检查"""
        try:
            # 模拟从服务器获取版本信息
            # 实际应用中，这里应该是一个HTTP请求到您的服务器
            response = urllib.request.urlopen(self.check_url)
            data = json.loads(response.read().decode('utf-8'))["data"]
            print(data)
            # 为了演示，我们模拟一个更新版本
            # 实际应用中，应该从服务器获取这些信息
            # data = {
            #     "version": "1.1.0",
            #     "pkgUrl": f"{DOWNLOAD_BASE_URL}app-1.1.0.zip",
            #     "release_notes": "新版本修复了一些bug并添加了新功能"
            # }
            
            self.latest_version = data["version"]
            self.download_url = DOWNLOAD_BASE_URL+data["pkgUrl"]
            
            # 比较版本号
            if self._compare_versions(self.latest_version, self.current_version) > 0:
                # 有新版本可用
                self.update_available.emit(self.latest_version, self.download_url)
                self.check_finished.emit(True)
            else:
                # 已经是最新版本
                self.check_finished.emit(False)
                
        except Exception as e:
            print(f"检查更新时出错: {e}")
            self.check_finished.emit(False)
    
    def _compare_versions(self, version1, version2):
        """比较两个版本号，返回1如果version1更新，0如果相同，-1如果version2更新"""
        v1_parts = list(map(int, version1.split('.')))
        v2_parts = list(map(int, version2.split('.')))
        
        for i in range(max(len(v1_parts), len(v2_parts))):
            v1 = v1_parts[i] if i < len(v1_parts) else 0
            v2 = v2_parts[i] if i < len(v2_parts) else 0
            
            if v1 > v2:
                return 1
            elif v1 < v2:
                return -1
        
        return 0  # 版本相同

class UpdateDialog(QDialog):
    """更新提示对话框"""
    def __init__(self, version, download_url, parent=None):
        super().__init__(parent)
        self.version = version
        self.download_url = download_url
        self.initUI()
        
    def initUI(self):
        self.setWindowTitle('发现新版本')
        self.setFixedSize(400, 200)
        
        # 居中显示
        self.center()
        
        layout = QVBoxLayout(self)
        
        # 标题
        title = QLabel(f'发现新版本: {self.version}')
        title.setFont(QFont('Arial', 14, QFont.Bold))
        title.setAlignment(Qt.AlignCenter)
        layout.addWidget(title)
        
        # 信息
        info = QLabel('有新版本可用，是否立即更新？')
        info.setAlignment(Qt.AlignCenter)
        layout.addWidget(info)
        
        # 按钮
        btn_layout = QHBoxLayout()
        
        self.update_btn = QPushButton('立即更新')
        self.update_btn.clicked.connect(self.accept)
        
        self.later_btn = QPushButton('稍后提醒')
        self.later_btn.clicked.connect(self.reject)
        
        btn_layout.addWidget(self.update_btn)
        btn_layout.addWidget(self.later_btn)
        
        layout.addLayout(btn_layout)
    
    def center(self):
        """将窗口居中显示"""
        qr = self.frameGeometry()
        cp = QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        # 初始化版本检查器
        self.version_checker = VersionChecker(APP_VERSION, UPDATE_URL)
        self.version_checker.update_available.connect(self.on_update_available)
        self.version_checker.check_finished.connect(self.on_check_finished)
        
        self.initUI()
        
        # 应用启动时自动检查更新
        self.check_for_updates(silent=True)
        
    def initUI(self):
        # 设置窗口标题和大小
        self.setWindowTitle('PyQt5 综合桌面应用')
        self.setGeometry(300, 300, 800, 600)
        
        # 创建中央部件和主布局
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.main_layout = QVBoxLayout(self.central_widget)
        
        # 创建标题
        self.create_header()
        
        # 创建选项卡
        self.create_tabs()
        
        # 创建状态栏
        self.statusBar().showMessage('准备就绪')
        
        # 设置样式
        self.setStyleSheet("""
            QMainWindow {
                background-color: #f5f5f5;
            }
            QTabWidget::pane {
                border: 1px solid #cccccc;
                background-color: #ffffff;
            }
            QTabBar::tab {
                background-color: #e1e1e1;
                padding: 8px 20px;
                margin-right: 2px;
            }
            QTabBar::tab:selected {
                background-color: #ffffff;
                border-bottom: 2px solid #4a86e8;
            }
            QPushButton {
                background-color: #4a86e8;
                color: white;
                border: none;
                padding: 8px 16px;
                border-radius: 4px;
            }
            QPushButton:hover {
                background-color: #3a76d8;
            }
            QPushButton:pressed {
                background-color: #2a66c8;
            }
            QLineEdit, QTextEdit, QComboBox {
                border: 1px solid #cccccc;
                border-radius: 4px;
                padding: 6px;
            }
            QGroupBox {
                font-weight: bold;
                border: 1px solid #cccccc;
                border-radius: 4px;
                margin-top: 12px;
            }
            QGroupBox::title {
                subcontrol-origin: margin;
                left: 10px;
                padding: 0 5px;
            }
        """)
        
    def check_for_updates(self, silent=False):
        """检查更新
        silent: 是否静默检查，如果为True，则只在有更新时显示提示
        """
        self.silent_check = silent
        self.version_checker.check_for_updates()
        if not silent:
            self.statusBar().showMessage('正在检查更新...')
    
    def on_update_available(self, version, download_url):
        """当有新版本可用时调用"""
        dialog = UpdateDialog(version, download_url, self)
        if dialog.exec_() == QDialog.Accepted:
            # 用户选择立即更新
            self.open_download_url(download_url)
    
    def on_check_finished(self, update_available):
        """检查更新完成时调用"""
        if not self.silent_check and not update_available:
            QMessageBox.information(self, '检查更新', '您的应用已是最新版本')
        self.statusBar().showMessage('准备就绪')
    
    def open_download_url(self, url):
        """直接下载并安装更新"""
        try:
            # 创建进度对话框
            progress_dialog = QProgressDialog("正在下载更新...", "取消", 0, 100, self)
            progress_dialog.setWindowTitle("下载更新")
            progress_dialog.setWindowModality(Qt.WindowModal)
            progress_dialog.setAutoClose(False)
            progress_dialog.setAutoReset(False)
            progress_dialog.show()

            
            # 创建临时目录用于保存下载的文件
            import tempfile
            import os
            temp_dir = tempfile.gettempdir()

            file_name = os.path.join(temp_dir, f"{APP_NAME}_update.exe" if os.name == 'nt' else f"{APP_NAME}_update.dmg")
            
            # 创建下载线程
            class DownloadThread(QThread):
                download_progress = pyqtSignal(int)
                download_complete = pyqtSignal(str)
                download_error = pyqtSignal(str)
                
                def __init__(self, url, file_path):
                    super().__init__()
                    self.url = url
                    self.file_path = file_path
                
                def run(self):
                    try:
                        import urllib.request
                        
                        def report_progress(block_num, block_size, total_size):
                            if total_size > 0:
                                progress = int(block_num * block_size * 100 / total_size)
                                self.download_progress.emit(min(progress, 100))
                        print(self.url, "url");
                        # 下载文件
                        urllib.request.urlretrieve(self.url, self.file_path, reporthook=report_progress)
                        self.download_complete.emit(self.file_path)
                    except Exception as e:
                        self.download_error.emit(str(e))
            
            # 创建并启动下载线程
            self.download_thread = DownloadThread(url, file_name)
            self.download_thread.download_progress.connect(progress_dialog.setValue)
            self.download_thread.download_complete.connect(self.install_update)
            self.download_thread.download_error.connect(self.handle_download_error)
            self.download_thread.start()
            
            # 连接取消按钮
            progress_dialog.canceled.connect(self.download_thread.terminate)
            
        except Exception as e:
            QMessageBox.critical(self, "下载错误", f"下载更新时发生错误：{str(e)}")
    
    def install_update(self, file_path):
        """安装下载的更新"""
        try:
            import os
            import subprocess
            
            QMessageBox.information(self, "下载完成", "更新已下载完成，将开始安装。")
            
            # 根据操作系统执行不同的安装命令
            if os.name == 'nt':  # Windows
                # 使用start命令启动安装程序
                subprocess.Popen(['start', file_path], shell=True)
            else:  # macOS
                # 打开DMG文件
                subprocess.Popen(['open', file_path])
            
            # 提示用户应用将关闭以完成更新
            result = QMessageBox.question(self, "完成更新", 
                                         "要完成更新，应用程序需要关闭。是否现在关闭应用程序？",
                                         QMessageBox.Yes | QMessageBox.No)
            if result == QMessageBox.Yes:
                QApplication.quit()
                
        except Exception as e:
            QMessageBox.critical(self, "安装错误", f"安装更新时发生错误：{str(e)}")
    
    def handle_download_error(self, error_message):
        """处理下载错误"""
        QMessageBox.critical(self, "下载错误", f"下载更新时发生错误：{error_message}")
        
    def create_header(self):
        header_layout = QHBoxLayout()
        
        # 标题标签
        title_label = QLabel(f'{APP_NAME} v{APP_VERSION}')
        title_label.setFont(QFont('Arial', 18, QFont.Bold))
        header_layout.addWidget(title_label)
        
        # 添加一些空间
        header_layout.addStretch()
        
        # 添加按钮
        check_update_button = QPushButton('检查更新')
        check_update_button.clicked.connect(lambda: self.check_for_updates(silent=False))
        header_layout.addWidget(check_update_button)
        
        help_button = QPushButton('帮助')
        help_button.clicked.connect(self.show_help)
        header_layout.addWidget(help_button)
        
        self.main_layout.addLayout(header_layout)
        
    def create_tabs(self):
        # 创建选项卡部件
        self.tabs = QTabWidget()
        
        # 表单选项卡
        self.form_tab = QWidget()
        self.create_form_tab()
        self.tabs.addTab(self.form_tab, '表单示例')
        
        # 控件展示选项卡
        self.widgets_tab = QWidget()
        self.create_widgets_tab()
        self.tabs.addTab(self.widgets_tab, '控件展示')
        
        # 文件操作选项卡
        self.file_tab = QWidget()
        self.create_file_tab()
        self.tabs.addTab(self.file_tab, '文件操作')
        
        self.main_layout.addWidget(self.tabs)
        
    def create_form_tab(self):
        layout = QVBoxLayout(self.form_tab)
        
        # 创建表单组
        form_group = QGroupBox('个人信息表单')
        form_layout = QFormLayout()
        
        # 添加表单字段
        self.name_edit = QLineEdit()
        form_layout.addRow('姓名:', self.name_edit)
        
        self.age_spin = QSpinBox()
        self.age_spin.setRange(1, 120)
        self.age_spin.setValue(25)
        form_layout.addRow('年龄:', self.age_spin)
        
        self.gender_combo = QComboBox()
        self.gender_combo.addItems(['男', '女', '其他'])
        form_layout.addRow('性别:', self.gender_combo)
        
        self.email_edit = QLineEdit()
        form_layout.addRow('邮箱:', self.email_edit)
        
        self.intro_text = QTextEdit()
        form_layout.addRow('自我介绍:', self.intro_text)
        
        form_group.setLayout(form_layout)
        layout.addWidget(form_group)
        
        # 添加提交按钮
        submit_button = QPushButton('提交表单')
        submit_button.clicked.connect(self.submit_form)
        layout.addWidget(submit_button, alignment=Qt.AlignRight)
        
    def create_widgets_tab(self):
        layout = QVBoxLayout(self.widgets_tab)
        
        # 创建水平布局来放置两列控件
        h_layout = QHBoxLayout()
        
        # 左侧控件组
        left_group = QGroupBox('基础控件')
        left_layout = QVBoxLayout()
        
        # 复选框
        self.check1 = QCheckBox('选项 1')
        self.check2 = QCheckBox('选项 2')
        self.check2.setChecked(True)
        left_layout.addWidget(self.check1)
        left_layout.addWidget(self.check2)
        
        # 单选按钮
        radio_layout = QHBoxLayout()
        self.radio1 = QRadioButton('单选 A')
        self.radio2 = QRadioButton('单选 B')
        self.radio1.setChecked(True)
        radio_layout.addWidget(self.radio1)
        radio_layout.addWidget(self.radio2)
        left_layout.addLayout(radio_layout)
        
        # 滑块
        slider_layout = QVBoxLayout()
        slider_label = QLabel('滑块控件:')
        self.slider = QSlider(Qt.Horizontal)
        self.slider.setRange(0, 100)
        self.slider.setValue(50)
        self.slider_value = QLabel('50')
        self.slider.valueChanged.connect(lambda v: self.slider_value.setText(str(v)))
        slider_layout.addWidget(slider_label)
        slider_layout.addWidget(self.slider)
        slider_layout.addWidget(self.slider_value, alignment=Qt.AlignCenter)
        left_layout.addLayout(slider_layout)
        
        left_group.setLayout(left_layout)
        h_layout.addWidget(left_group)
        
        # 右侧控件组
        right_group = QGroupBox('动态控件')
        right_layout = QVBoxLayout()
        
        # 进度条
        progress_label = QLabel('进度条:')
        self.progress_bar = QProgressBar()
        self.progress_bar.setValue(0)
        
        # 进度条控制按钮
        progress_buttons = QHBoxLayout()
        start_button = QPushButton('开始')
        reset_button = QPushButton('重置')
        start_button.clicked.connect(self.start_progress)
        reset_button.clicked.connect(lambda: self.progress_bar.setValue(0))
        progress_buttons.addWidget(start_button)
        progress_buttons.addWidget(reset_button)
        
        right_layout.addWidget(progress_label)
        right_layout.addWidget(self.progress_bar)
        right_layout.addLayout(progress_buttons)
        
        # 添加一个动态更新的时间标签
        time_label = QLabel('当前计数:')
        self.counter_label = QLabel('0')
        self.counter = 0
        
        counter_buttons = QHBoxLayout()
        count_button = QPushButton('计数')
        count_button.clicked.connect(self.increment_counter)
        counter_buttons.addWidget(count_button)
        
        right_layout.addWidget(time_label)
        right_layout.addWidget(self.counter_label)
        right_layout.addLayout(counter_buttons)
        
        right_group.setLayout(right_layout)
        h_layout.addWidget(right_group)
        
        layout.addLayout(h_layout)
        
    def create_file_tab(self):
        layout = QVBoxLayout(self.file_tab)
        
        # 文件操作组
        file_group = QGroupBox('文件操作')
        file_layout = QVBoxLayout()
        
        # 文件路径显示
        path_layout = QHBoxLayout()
        path_label = QLabel('文件路径:')
        self.file_path = QLineEdit()
        self.file_path.setReadOnly(True)
        browse_button = QPushButton('浏览...')
        browse_button.clicked.connect(self.browse_file)
        path_layout.addWidget(path_label)
        path_layout.addWidget(self.file_path)
        path_layout.addWidget(browse_button)
        file_layout.addLayout(path_layout)
        
        # 文件内容
        content_label = QLabel('文件内容:')
        self.file_content = QTextEdit()
        file_layout.addWidget(content_label)
        file_layout.addWidget(self.file_content)
        
        # 文件操作按钮
        file_buttons = QHBoxLayout()
        load_button = QPushButton('加载文件')
        save_button = QPushButton('保存文件')
        load_button.clicked.connect(self.load_file)
        save_button.clicked.connect(self.save_file)
        file_buttons.addWidget(load_button)
        file_buttons.addWidget(save_button)
        file_layout.addLayout(file_buttons)
        
        file_group.setLayout(file_layout)
        layout.addWidget(file_group)
        
    def submit_form(self):
        name = self.name_edit.text()
        age = self.age_spin.value()
        gender = self.gender_combo.currentText()
        email = self.email_edit.text()
        
        if not name or not email:
            QMessageBox.warning(self, '表单不完整', '请填写姓名和邮箱字段')
            return
            
        message = f'表单提交成功!\n\n姓名: {name}\n年龄: {age}\n性别: {gender}\n邮箱: {email}'
        QMessageBox.information(self, '表单已提交', message)
        self.statusBar().showMessage('表单已提交')
        
    def start_progress(self):
        self.progress_value = 0
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_progress)
        self.timer.start(100)
        
    def update_progress(self):
        self.progress_value += 1
        self.progress_bar.setValue(self.progress_value)
        if self.progress_value >= 100:
            self.timer.stop()
            
    def increment_counter(self):
        self.counter += 1
        self.counter_label.setText(str(self.counter))
        
    def browse_file(self):
        file_path, _ = QFileDialog.getOpenFileName(self, '选择文件', '', '所有文件 (*)')
        if file_path:
            self.file_path.setText(file_path)
            
    def load_file(self):
        path = self.file_path.text()
        if not path:
            QMessageBox.warning(self, '错误', '请先选择一个文件')
            return
            
        try:
            with open(path, 'r', encoding='utf-8') as file:
                content = file.read()
                self.file_content.setText(content)
                self.statusBar().showMessage(f'文件已加载: {path}')
        except Exception as e:
            QMessageBox.critical(self, '错误', f'无法加载文件: {str(e)}')
            
    def save_file(self):
        path = self.file_path.text()
        if not path:
            path, _ = QFileDialog.getSaveFileName(self, '保存文件', '', '所有文件 (*)')
            if not path:
                return
            self.file_path.setText(path)
            
        try:
            content = self.file_content.toPlainText()
            with open(path, 'w', encoding='utf-8') as file:
                file.write(content)
                self.statusBar().showMessage(f'文件已保存: {path}')
                QMessageBox.information(self, '成功', '文件保存成功')
        except Exception as e:
            QMessageBox.critical(self, '错误', f'无法保存文件: {str(e)}')
            
    def show_help(self):
        help_text = """
        <h2>PyQt5 桌面应用使用帮助</h2>
        <p><b>表单示例:</b> 展示了基本的表单控件和数据验证</p>
        <p><b>控件展示:</b> 展示了各种PyQt5控件的使用方法</p>
        <p><b>文件操作:</b> 演示了如何进行基本的文件读写操作</p>
        <p>这是一个PyQt5示例应用，用于展示PyQt5的基本功能和用法。</p>
        """
        QMessageBox.information(self, '帮助', help_text)


def main():
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()